
//
// 120805 - AH - (AH) Created.
// 120813a- AH - (AH) Finished implementation.
//

package org.soekrat.server.serialization.json;

import java.io.BufferedReader;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

/**
 * <p>
 *   Object that translates JSON request to the equivalent HTTP request.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class JsonToHttpRequest
{
  /**
   * <p>
   *   Result of parsing the JSON.
   * </p>
   * @author Arne Halvorsen (AH)
   * @author Laetitia Le Chatton (LLC)
   */
  public final static class ParseResult
  {
    /**
     * <p>
     *   If {@code false} is
     *   {@link #res} an error message, if {@code true} is it an compiled 
     *   request URL.
     * </p>
     */
    public final boolean ok;
    
    /**
     * <p>
     *   If
     *   {@link #ok} is {@code true} this is a compiled request URL else is it 
     *   an error message.
     * </p>
     */
    public final String res;
    
    /**
     * <p>
     *   Constructor.
     * </p>
     * @param ok  {@code true} if {@code res} is a compiled URL.
     * @param res
     */
    private ParseResult(boolean ok, String res){ this.ok=ok; this.res=res; }
    
    @Override
    public String toString() 
    {
      StringBuilder sb=new StringBuilder();
      sb.append("ok=").append(ok).append(", res='").append(res).append("'");
      return sb.toString();
    }
    
  }
  
  private final String m_stem;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param stem Url's stem.
   */
  public JsonToHttpRequest(String stem)
  {
    if (stem==null)
    {
      throw new NullPointerException("stem");
    }
    
    m_stem=stem;
  }
  
  /**
   * <p>
   *   Gets stem of URLs to generate.
   * </p>
   * @return Stem.
   */
  public String getStem(){ return m_stem; }
  
  /**
   * <p>
   *   Parses JSON file.
   * </p>
   * @param f {@link File} to parse.
   * @return Result.
   * @throws IOException If fails to read or parse.
   */
  public ParseResult toRequestUrl(File f) throws IOException
  {
    if (f==null)
    {
      throw new NullPointerException("f");
    }
    
    CharArrayWriter caw=new CharArrayWriter();
    PrintWriter pw=new PrintWriter(caw);
    
    FileReader fr=new FileReader(f);
    BufferedReader br=new BufferedReader(fr);
    String line=br.readLine();
    while (line!=null)
    {
      pw.println(line);
      line=br.readLine();
    }
    
    pw.flush();
    String json=caw.toString();
    
    return toRequestUrl(json);
  }
  
  /**
   * <p>
   *   Parses JSON.
   * </p>
   * @param json JSON code to parse.
   * @return Result.
   */
  public ParseResult toRequestUrl(String json)
  {
    StringBuilder sb=new StringBuilder();
    
    JsonElement parsed=new JsonParser().parse(json);
    JsonObject jo=parsed.getAsJsonObject();
    
    JsonElement req=jo.get("req");
    if (req==null)
    {
      return new ParseResult(false, "missing request");
    }
    
    sb.append(m_stem).append("/").append(req.getAsString());
    
    boolean first=true;
    for (Map.Entry<String, JsonElement> e : jo.entrySet())
    {
      String name=e.getKey();
      String val=e.getValue().getAsString();
      
      if (!name.equals("req"))
      {
        if (first)
        {
          sb.append("?");
          first=false;
        }
        else
        {
          sb.append(",");
        }
        
        try
        {
          sb.append(name).append("=").append(URLEncoder.encode(val, "UTF-8"));
        }
        catch (UnsupportedEncodingException uex)
        {
          Error err=new Error();
          err.initCause(uex);
          throw err;
        }
      }
    }
    
    return new ParseResult(true, sb.toString());
  }
  
  /**
   * <p>
   *   Simple test program.
   * </p>
   * @param args Command line arguments, not used.
   */
  public static void main(String[] args) 
  {
    try
    {
      File f=new File("./testjson.json"); 
      
      JsonToHttpRequest jthr=new JsonToHttpRequest("test");
      
      ParseResult req=jthr.toRequestUrl(f);
      
      System.out.println(req);
      
      System.exit(0);
    }
    catch (IOException iox)
    {
      iox.printStackTrace();
      System.exit(-1);
    }
  }
  
}
